ahngbeom
App
Flutter App 백화 현상 해결
Back-End
결제 서비스 MSA 아키텍쳐 전환
DBA
MySQL Version Up
Front-End
Full-Stack
Infra
네트워크에 대해서
Gemini에게 네트워크 인프라 구성도 요청하기
클라우드 서비스에 대해서
Dockerfile 분석
Kubernetes Helm 차트 분석
Introduction
Home
Contact
Copyright © 2024 |
Yankos
Home
>
Back-End
> 결제 서비스 MSA 아키텍쳐 전환
Now Loading ...
결제 서비스 MSA 아키텍쳐 전환
0. Intro
우리는 PG사 API와 연동하여 결제 서비스를 클라이언트에게 제공해주고 있다. 결제 서비스 내에서도 결제 수단 등록/삭제, 결제 수단 조회와 등록된 결제 수단을 통한 책정 금액 결제 또는 책정 금액의 청구서를 카카오톡으로 발송 우리는 가맹점과 소비자의 중간 매개체 역할이며, 소비자가 이용한 서비스에 대한 책정 금액을 가맹점이 결정하여 우리에게 전달한다. 우리는 책정된 금액과 소비자 정보를 전달받아 결제 방식을 결정한다. 만약 소비자가 우리의 플랫폼 APP의 회원일 경우, PG사에서 제공해주는 자동 결제 시스템을 통해 소비자가 미리 등록한 결제 수단으로 즉시 결제 요청한다. 소비자가 미리 등록한 결제 수단이 없거나 결제 수단에 문제가 있다고 판단될 경우, 소비자의 연락처를 통해 카카오톡 청구서를 발송한다. 소비자가 우리의 플랫폼 APP의 회원이 아닐 경우, 즉시 카카오톡 청구서 방식으로 요청한다. 결제 요청 후, PG사로부터 Callback API를 통해 결제 요청 결과를 수신 받는다. 환불이 필요할 경우, 결제 요청 당시 생성한 청구서 ID와 요청 금액을 전달하여 환불 요청한다. 재결제가 필요할 경우, 환불 요청 후, 새로운 청구서 ID를 생성하여 결제 요청한다. 기존 결제 서비스는 모든 외부 모듈들이 필수로 주입 받고 있는 common 모듈 안에 구현되어있어서 결제 서비스가 필요하지 않더라도 인스턴스를 생성하고 있었다. 우리는 기존 서비스 기능에 대한 고도화 작업 및 신규 기능 추가 작업으로 인해 점차 리소스 비용이 증가하고 있었다. 따라서 결제 서비스 전용 모듈을 분리하여 MSA 아키텍처로 전환하기로 결정하였다. 이를 통해 결제 서비스의 독립성을 확보하고, 서비스 간의 의존성을 줄이며, 향후 기능 확장 및 유지보수를 용이하게 할 수 있을 것으로 기대하고 있다. 또한, MSA 아키텍처로의 전환은 각 서비스의 배포 및 확장을 독립적으로 수행할 수 있는 기반을 마련해줄 것이다. 목표 결제 서비스의 독립성을 확보하고, 서비스 간의 의존성을 줄인다. 향후 기능 확장 및 유지보수를 용이하게 한다. 각 서비스의 배포 및 확장을 독립적으로 수행할 수 있는 기반을 마련한다. 추상화 구조로 설계해본다. 어댑터 패턴 (Adapter Pattern) 이란? 기존 복잡한 VIEW TABLE을 사용하지 않는 방향으로, 제거하는 방향으로 설계해보자. 결제 모듈만이 관리하는 테이블과 각 클라이언트가 관리하는 테이블을 분리하고 각자 관리한다.
Back-End
1. Legacy DB 테이블 정리
하나의 메인 스키마에서 모든 서비스의 데이터를 담고 있는 상황에서 별도 스키마를 생성하여 결제 서비스와 관련된 데이터를 분리하려고 한다. 단, 결제 서비스 스키마에는 PG사와 연동, 통신 과정을 통해 생성되는 데이터만 담고, 외부에서 결제 서비스를 사용하려는 도메인에서는 결제 서비스 스키마의 테이블 간의 맵핑 테이블을 통해 데이터를 활용한다. Drop Table tb_ 접두사로 생성된 결제 테이블 제거 뷰 테이블 제거 Create Table 메인 스키마 도메인과 결제 서비스 간의 맵핑 테이블 생성 최근 결제 결과 상태 저장 테이블 생성 결제 결과 상태 이력 테이블 생성 도메인과 결제 수단 서비스 간의 맵핑 테이블 생성 결제 수단 상태 저장 테이블 생성 결제 스키마 결제 스키마에서는 가공하지 않은 데이터만을 저장한다. 연동 PG사 간 결제 요청과 응답 순수 데이터를 저장할 테이블 생성 최근 결제 결과 상태 저장 테이블 생성 결제 결과 상태 이력 테이블 생성 연동 PG사 간 결제 수단 등록 요청과 응답 순수 데이터를 저장할 테이블 생성 결제 수단 상태 저장 테이블 생성 결제 수단 상태 이력 테이블 생성 API 연동 통신 로깅 테이블 생성 Request Body를 하나의 컬럼에 JSON 형태로 저장한다. Response Body를 하나의 컬럼에 JSON 형태로 저장한다.
Back-End
· 2025-08-31
1. 결제 서비스 인터페이스 추상화
결제 서비스의 핵심 기능들을 추상화한 PaymentPort 인터페이스에 대해 설명합니다. 이 인터페이스는 포트 앤 어댑터 패턴(헥사고날 아키텍처)을 적용하여 결제 시스템의 핵심 비즈니스 로직과 외부 시스템과의 통신을 분리하는 역할을 합니다. 인터페이스 구조 public interface PaymentPort { PaymentResponse payment(PaymentPayload payload, PaymentAdapterRunnable<BaseResponse> runnable); ReadResponse read(ReadPayload payload); RefundResponse refund(RefundPayload payload, PaymentAdapterRunnable<RefundResponse> runnable); KakaoTalkResponse sendBill(KakaoTalkPayload payload, PaymentAdapterRunnable<KakaoTalkResponse> runnable); DestroyResponse destroy(DestroyPayload payload, PaymentAdapterRunnable<DestroyResponse> successRunnable); default PaymentCallbackResponse callback(PaymentCallbackPayload payload, String hash) { return null; } } 주요 메서드 설명 1. payment() - 결제 요청 실제 결제 처리를 수행하는 메서드 PaymentAdapterRunnable을 통해 결제 처리 중 발생하는 이벤트를 처리할 수 있는 콜백 제공 결제 요청에 대한 응답으로 PaymentResponse 반환 2. read() - 결제 조회 결제 정보를 조회하는 메서드 단순 조회이므로 별도의 runnable 콜백이 필요하지 않음 ReadPayload를 통해 조회 조건을 전달받아 ReadResponse로 결과 반환 3. refund() - 환불 요청 결제 취소 및 환불 처리를 수행하는 메서드 환불 처리 시 발생하는 이벤트를 처리하기 위한 runnable 콜백 포함 환불 처리 결과를 RefundResponse로 반환 4. sendBill() - 결제 청구서 전송 결제 청구서를 생성하고 전송하는 메서드 청구서 전송 과정의 이벤트를 처리하기 위한 runnable 콜백 포함 청구서 전송 결과를 KakaoTalkResponse로 반환 5. destroy() - 결제 청구서 파기 기존에 생성된 결제 청구서를 파기하는 메서드 청구서 파기 처리 결과를 이벤트로 처리하기 위한 runnable 콜백 포함 파기 처리 결과를 DestroyResponse로 반환 6. callback() - 결제 요청 결과 콜백 결제 요청 후 외부 시스템(PG사)으로부터 결제 요청 결과 응답을 처리하는 메서드 default 메서드로 구현되어 필요한 경우에만 오버라이드하여 사용 가능 해시값을 통한 검증 로직 포함 PaymentAdapterRunnable의 역할 각 메서드에서 사용되는 PaymentAdapterRunnable은 결제 처리 과정에서 발생하는 다양한 상황을 처리하기 위한 콜백 인터페이스입니다. 주요 기능은 다음과 같습니다: 성공/실패 상황에 대한 별도 처리 처리 과정의 로깅 비동기 처리 지원 예외 상황 핸들링 이러한 인터페이스 추상화를 통해 결제 시스템은: 구현체 교체의 용이성 테스트 용이성 시스템 결합도 감소 확장성 향상 등의 이점을 얻을 수 있습니다.
Back-End
· 2025-09-01
2. 결제 서비스 어댑터 구현체 설계
결제 서비스의 PaymentPort 인터페이스를 구현한 PaymentAdapter 클래스에 대해 설명합니다. 이 클래스는 실제 결제 처리를 수행하는 구현체로서, 외부 결제 시스템과의 통신을 담당합니다. 클래스 구조 @Service @Transactional(transactionManager = "paymentTransactionManager") @RequiredArgsConstructor public class PaymentAdapter implements PaymentPort { private final MyPgProducer producer; private final PaymentService paymentService; private final ObjectMapper objectMapper; private final AES aesCrypto; // ... } 주요 특징 1. 스프링 컴포넌트 설정 @Service: 스프링의 서비스 계층 컴포넌트로 등록 @Transactional: 결제 트랜잭션 관리를 위한 설정 (paymentTransactionManager 사용) @RequiredArgsConstructor: 의존성 주입을 위한 생성자 자동 생성 2. 의존성 구성 MyPgProducer: PG사 시스템과의 통신을 담당하는 컴포넌트 PaymentService: 결제 정보 영속성 관리를 위한 서비스 ObjectMapper: JSON 데이터 변환을 위한 유틸리티 AES: 암호화/복호화를 위한 유틸리티 주요 메서드 구현 1. payment() - 결제 처리 구현 @Override public PaymentResponse payment(PaymentPayload payload, PaymentAdapterRunnable<BaseResponse> runnable) { PaymentRequest request = PaymentRequest.from(payload); Payment entity = paymentService.update(request.toEntity()); runnable.createUuidRunnable().run(entity.getUuid().toString()); // ... } 결제 요청 데이터를 PG사 요구 형식으로 변환 결제 정보를 데이터베이스에 저장 UUID 생성 및 처리 결과 콜백 실행 에러 발생 시 별도 처리 2. sendBill() - 결제 청구서 발송 결제 청구서 데이터 생성 및 PG사 전송 응답 결과에 따른 처리 분기 성공/실패 시나리오에 대한 콜백 처리 결제 정보 업데이트 및 응답 생성 3. callback() - 결제 콜백 처리 @Override public PaymentCallbackResponse callback(PaymentCallbackRequest payload, String hash) { ApiHistories histories = producer.requestLogging(payload, CALLBACK_PAYMENT.getUri()); Payment entity = paymentService.findPaymentByCallbackHash(decryptCallbackHash(hash)); // ... } 콜백 요청 로깅 해시값을 통한 결제 정보 검증 결제 상태 업데이트 응답 생성 및 로깅 4. 공통 처리 패턴 모든 메서드는 다음과 같은 공통된 패턴을 따릅니다: 요청 데이터 변환 데이터베이스 엔티티 처리 PG사 API 호출 에러 처리 결과 업데이트 콜백 실행 응답 반환 에러 처리 전략 if (response.isError()) { runnable.errorRunnable().run(entity.getUuid().toString(), response); return ErrorResponse.from(/*...*/); } 모든 PG사 통신에서 에러 체크 에러 발생 시 별도 콜백 실행 트랜잭션 롤백 처리 클라이언트에 적절한 에러 응답 반환 보안 처리 AES 암호화를 통한 콜백 해시 검증 민감한 결제 정보 보호 API 키 기반의 인증 처리 트랜잭션 관리 전용 트랜잭션 매니저 사용 결제 데이터의 정합성 보장 실패 시 롤백 처리 이러한 구현을 통해 PaymentAdapter는: 결제 처리의 안정성 보장 외부 시스템과의 견고한 통합 에러 상황에 대한 안전한 처리 트랜잭션 정합성 유지 보안 요구사항 충족 등을 달성하고 있습니다.
Back-End
· 2025-09-01
3. PG사 외부 API 통신을 위한 RestClient 설계
Spring Framework 6.1에서 도입된 RestClient와 @HttpExchange 어노테이션을 활용한 선언적 HTTP 클라이언트 구현에 대해 설명합니다. 인터페이스 기반 RestClient 설계 Spring의 @HttpExchange 어노테이션을 사용하여 선언적으로 HTTP 클라이언트를 정의할 수 있습니다. @Component @HttpExchange public interface PgPaymentApiRestClient { @PostExchange("...") 바로결제ResponseBody 바로결제(@RequestBody 바로결제RequestBody request); @PostExchange("...") 청구서카카오톡발송ResponseBody 청구서카카오톡발송(@RequestBody 청구서카카오톡발송RequestBody request); @PostExchange("...") 청구서URL조회ResponseBody 청구서URL조회(@RequestBody 청구서URL조회RequestBody request); @PostExchange("...") 결제정보조회ResponseBody 결제정보조회(@RequestBody 결제정보조회RequestBody request); @PostExchange("...") 환불요청ResponseBody 환불요청(@RequestBody 환불요청RequestBody request); @PostExchange("...") 청구서파기ResponseBody 청구서파기(@RequestBody 청구서파기RequestBody request); } 인터페이스 설명 PgPaymentApiRestClient 인터페이스는 다음과 같은 특징을 가집니다: 선언적 HTTP 통신 @HttpExchange 어노테이션으로 HTTP 클라이언트임을 선언 각 메서드에 @PostExchange 어노테이션으로 POST 요청 정의 요청/응답 DTO를 통한 타입 안전성 보장 메서드 구성 바로결제: 즉시 결제 요청 처리 청구서카카오톡발송: 결제 청구서 카카오톡 발송 청구서URL조회: 결제 청구서 URL 정보 조회 결제정보조회: 기존 결제 내역 조회 환불요청: 결제 취소 및 환불 처리 청구서파기: 발급된 청구서 무효화 요청/응답 매핑 @RequestBody를 통한 요청 본문 자동 매핑 응답 데이터의 자동 역직렬화 RestClient 설정 아래는 RestClient의 구성과 설정을 담당하는 설정 클래스입니다. @Slf4j @Configuration @RequiredArgsConstructor public class RestClientConfig { @Value("${payment.pg.api.url}") private String pgApiUri; @Bean public PgPaymentApiRestClient pgPaymentApiRestClient() { return HttpServiceProxyFactory.builderFor( RestClientAdapter.create(paymentRestClientBuilder().baseUrl(pgApiUri).build())) .build() .createClient(PgPaymentApiRestClient.class); } @Bean public RestClient.Builder paymentRestClientBuilder() { return RestClient.builder() .defaultHeader(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultStatusHandler( HttpStatusCode::isError, (request, response) -> { log.error("httpRequest: {}, {}", request.getHeaders(), request.getURI()); log.error("httpResponse: {}, {}", response.getStatusCode(), response.getStatusText()); throw new PaymentException(response.toString()); }); } } 설정 클래스 주요 특징 환경 설정 @Value 어노테이션으로 PG사 API URL 주입 외부 설정을 통한 유연한 환경 관리 RestClient 빌더 설정 Content-Type과 Accept 헤더 기본값 설정 에러 상태 코드에 대한 전역 핸들러 구성 상세한 에러 로깅 구현 프록시 팩토리 설정 HttpServiceProxyFactory를 통한 인터페이스 구현체 자동 생성 RestClient 어댑터 구성 동적 프록시를 통한 HTTP 클라이언트 생성 장점 코드 간결성 인터페이스 선언만으로 HTTP 클라이언트 구현 보일러플레이트 코드 최소화 타입 안전성 컴파일 시점에 타입 검증 DTO를 통한 요청/응답 데이터 구조화 유지보수성 선언적 프로그래밍으로 가독성 향상 중앙화된 설정으로 일관성 있는 구현 확장성 새로운 API 엔드포인트 추가가 용이 공통 설정의 유연한 확장 주의사항 에러 처리 적절한 예외 처리 로직 구현 필요 상세한 로깅으로 문제 추적 가능성 확보 타임아웃 설정 적절한 타임아웃 값 설정 필요 네트워크 지연 상황 고려 보안 민감한 정보의 로깅 제외 적절한 인증/인가 처리 이러한 설계를 통해 PG사와의 안정적이고 유지보수가 용이한 HTTP 통신을 구현할 수 있습니다.
Back-End
· 2025-09-01
4. 결제 서비스 Runnable 패턴 구현
결제 처리 과정에서 발생하는 다양한 이벤트를 처리하기 위한 PaymentAdapterRunnable 구현에 대해 설명합니다. 이 클래스는 결제 처리의 각 단계에서 발생하는 이벤트(UUID 생성, 성공, 실패)를 함수형 인터페이스를 통해 처리합니다. 클래스 구조 public record PaymentAdapterRunnable<T>( CreateUuidRunnable createUuidRunnable, SuccessRunnable<T> successRunnable, ErrorRunnable errorRunnable) { public static PaymentAdapterRunnable<BaseResponse> paymentRunnable( CreateUuidRunnable createUuidRunnable, SuccessRunnable<BaseResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(createUuidRunnable, successRunnable, errorRunnable); } public static PaymentAdapterRunnable<Void> callbackRunnable( SuccessRunnable<Void> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } public static PaymentAdapterRunnable<TalkResponse> sendBillKakaoTalkRunnable( SuccessRunnable<KakaoTalkResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } public static PaymentAdapterRunnable<UrlResponse> getBillUrlRunnable( SuccessRunnable<UrlResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } public static PaymentAdapterRunnable<RefundResponse> refundRunnable( SuccessRunnable<RefundResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } public static PaymentAdapterRunnable<DestroyResponse> destroyRunnable( SuccessRunnable<DestroyResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } 주요 컴포넌트 1. Record 클래스 정의 public record PaymentAdapterRunnable<T>( CreateUuidRunnable createUuidRunnable, SuccessRunnable<T> successRunnable, ErrorRunnable errorRunnable) { Java 21의 Record 기능을 활용한 불변 데이터 클래스 제네릭 타입 <T>를 통한 다양한 응답 타입 지원 세 가지 핵심 Runnable 컴포넌트 포함: CreateUuidRunnable: UUID 생성 시점의 콜백 SuccessRunnable<T>: 성공 처리 콜백 ErrorRunnable: 오류 처리 콜백 2. 정적 팩토리 메서드 결제 요청 Runnable public static PaymentAdapterRunnable<BaseResponse> paymentRunnable( CreateUuidRunnable createUuidRunnable, SuccessRunnable<BaseResponse> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(createUuidRunnable, successRunnable, errorRunnable); } 모든 콜백을 포함한 전체 Runnable 생성 결제 요청 시 사용되는 기본 구현 콜백 Runnable public static PaymentAdapterRunnable<Void> callbackRunnable( SuccessRunnable<Void> successRunnable, ErrorRunnable errorRunnable) { return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable); } UUID 생성이 필요 없는 콜백 처리용 빈 UUID 생성 콜백 포함 기타 특화된 Runnable sendBillKakaoTalkRunnable: 카카오톡 청구서 발송 getBillUrlRunnable: 청구서 URL 조회 refundRunnable: 환불 처리 destroyRunnable: 청구서 파기 설계 특징 1. 함수형 프로그래밍 활용 람다식을 통한 간결한 콜백 구현 함수형 인터페이스를 통한 유연한 이벤트 처리 2. 제네릭을 통한 타입 안전성 응답 타입에 따른 타입 파라미터 지정 컴파일 시점의 타입 검증 3. 불변성 보장 Record 클래스를 통한 불변 객체 구현 스레드 안전성 확보 4. 메서드 특화 각 결제 프로세스에 특화된 팩토리 메서드 불필요한 콜백 제거로 효율성 향상 사용 예시 // 결제 요청 Runnable 생성 PaymentAdapterRunnable<BaseResponse> runnable = PaymentAdapterRunnable.paymentRunnable( uuid -> log.info("UUID created: {}", uuid), (uuid, response) -> log.info("Payment success: {}", response), (uuid, error) -> log.error("Payment failed: {}", error) ); // 환불 요청 Runnable 생성 PaymentAdapterRunnable<RefundResponse> refundRunnable = PaymentAdapterRunnable.refundRunnable( (uuid, response) -> log.info("Refund success: {}", response), (uuid, error) -> log.error("Refund failed: {}", error) ); 장점 코드 재사용성 공통 콜백 패턴 표준화 중복 코드 제거 유연성 다양한 결제 프로세스에 대응 콜백 조합의 자유로운 구성 유지보수성 명확한 책임 분리 테스트 용이성 타입 안전성 컴파일 타임 타입 체크 런타임 에러 방지 주의사항 콜백 체인 관리 과도한 콜백 중첩 방지 적절한 에러 처리 구현 메모리 관리 콜백 객체의 적절한 해제 순환 참조 방지 디버깅 콜백 실행 추적을 위한 로깅 구현 명확한 에러 메시지 제공 이러한 Runnable 패턴 구현을 통해 결제 처리의 각 단계에서 발생하는 이벤트를 효율적이고 유연하게 처리할 수 있습니다.
Back-End
· 2025-09-01
Intro
우리는 PG사 API와 연동하여 결제 서비스를 클라이언트에게 제공해주고 있다. 결제 서비스 내에서도 결제 수단 등록/삭제, 결제 수단 조회와 등록된 결제 수단을 통한 책정 금액 결제 또는 책정 금액의 청구서를 카카오톡으로 발송 우리는 가맹점과 소비자의 중간 매개체 역할이며, 소비자가 이용한 서비스에 대한 책정 금액을 가맹점이 결정하여 우리에게 전달한다. 우리는 책정된 금액과 소비자 정보를 전달받아 결제 방식을 결정한다. 만약 소비자가 우리의 플랫폼 APP의 회원일 경우, PG사에서 제공해주는 자동 결제 시스템을 통해 소비자가 미리 등록한 결제 수단으로 즉시 결제 요청한다. 소비자가 미리 등록한 결제 수단이 없거나 결제 수단에 문제가 있다고 판단될 경우, 소비자의 연락처를 통해 카카오톡 청구서를 발송한다. 소비자가 우리의 플랫폼 APP의 회원이 아닐 경우, 즉시 카카오톡 청구서 방식으로 요청한다. 결제 요청 후, PG사로부터 Callback API를 통해 결제 요청 결과를 수신 받는다. 환불이 필요할 경우, 결제 요청 당시 생성한 청구서 ID와 요청 금액을 전달하여 환불 요청한다. 재결제가 필요할 경우, 환불 요청 후, 새로운 청구서 ID를 생성하여 결제 요청한다. 기존 결제 서비스는 모든 외부 모듈들이 필수로 주입 받고 있는 common 모듈 안에 구현되어있어서 결제 서비스가 필요하지 않더라도 인스턴스를 생성하고 있었다. 우리는 기존 서비스 기능에 대한 고도화 작업 및 신규 기능 추가 작업으로 인해 점차 리소스 비용이 증가하고 있었다. 따라서 결제 서비스 전용 모듈을 분리하여 MSA 아키텍처로 전환하기로 결정하였다. 이를 통해 결제 서비스의 독립성을 확보하고, 서비스 간의 의존성을 줄이며, 향후 기능 확장 및 유지보수를 용이하게 할 수 있을 것으로 기대하고 있다. 또한, MSA 아키텍처로의 전환은 각 서비스의 배포 및 확장을 독립적으로 수행할 수 있는 기반을 마련해줄 것이다. 목표 결제 서비스의 독립성을 확보하고, 서비스 간의 의존성을 줄인다. 향후 기능 확장 및 유지보수를 용이하게 한다. 각 서비스의 배포 및 확장을 독립적으로 수행할 수 있는 기반을 마련한다. 추상화 구조로 설계해본다. 어댑터 패턴 (Adapter Pattern) 이란? 기존 복잡한 VIEW TABLE을 사용하지 않는 방향으로, 제거하는 방향으로 설계해보자. 결제 모듈만이 관리하는 테이블과 각 클라이언트가 관리하는 테이블을 분리하고 각자 관리한다.
Back-End
Legacy DB 테이블 정리
하나의 메인 스키마에서 모든 서비스의 데이터를 담고 있는 상황에서 별도 스키마를 생성하여 결제 서비스와 관련된 데이터를 분리하려고 한다. 단, 결제 서비스 스키마에는 PG사와 연동, 통신 과정을 통해 생성되는 데이터만 담고, 외부에서 결제 서비스를 사용하려는 도메인에서는 결제 서비스 스키마의 테이블 간의 맵핑 테이블을 통해 데이터를 활용한다. Drop Table tb_ 접두사로 생성된 결제 테이블 제거 뷰 테이블 제거 Create Table 메인 스키마 도메인과 결제 서비스 간의 맵핑 테이블 생성 최근 결제 결과 상태 저장 테이블 생성 결제 결과 상태 이력 테이블 생성 도메인과 결제 수단 서비스 간의 맵핑 테이블 생성 결제 수단 상태 저장 테이블 생성 결제 스키마 결제 스키마에서는 가공하지 않은 데이터만을 저장한다. 연동 PG사 간 결제 요청과 응답 순수 데이터를 저장할 테이블 생성 최근 결제 결과 상태 저장 테이블 생성 결제 결과 상태 이력 테이블 생성 연동 PG사 간 결제 수단 등록 요청과 응답 순수 데이터를 저장할 테이블 생성 결제 수단 상태 저장 테이블 생성 결제 수단 상태 이력 테이블 생성 API 연동 통신 로깅 테이블 생성 Request Body를 하나의 컬럼에 JSON 형태로 저장한다. Response Body를 하나의 컬럼에 JSON 형태로 저장한다.
Back-End
· 2025-08-31
어댑터 패턴 설계
public interface PaymentPort { // 결제 요청 PaymentResponse payment(PaymentRequest payload, PaymentAdapterRunnable<BaseResponse> runnable); // 결제 조회 ReadResponse read(ReadRequest payload); // 환불 요청 RefundResponse refund(RefundRequest payload, PaymentAdapterRunnable<RefundResponse> runnable); // 결제 청구서 카카오톡 전송 KakaoTalkResponse sendBill(TalkRequest payload, PaymentAdapterRunnable<KakaoTalkResponse> runnable); // 결제 청구서 파기 DestroyResponse destroy( DestroyRequest payload, PaymentAdapterRunnable<DestroyResponse> successRunnable); // 결제 요청 결과 Callback default PaymentCallbackResponse callback(PaymentCallbackRequest payload, String hash) { return null; } }
Back-End
· 2025-09-01
<
>
Touch background to close